package org.dftproject.genesis.ui.actions;

import org.dftproject.genesis.ui.editors.TabPartEditorInput;
import org.dftproject.genesis.ui.pages.IPageHistoryListener;
import org.dftproject.genesis.ui.pages.PageHistory;
import org.dftproject.genesis.ui.pages.PageHistoryEntry;
import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;

public class PageHistoryAction extends ActiveEditorAction implements IWorkbenchAction {

	public static final String FORWARD = "org.eclipse.ui.navigate.forwardHistory";
	public static final String BACK = "org.eclipse.ui.navigate.backwardHistory";
	
	private static final int MAX_HISTORY_ENTRIES = 10;
	
	private final boolean forward;
	
	private PageHistory activePageHistory;
	
	private final IPageHistoryListener pageHistoryListener = new PageHistoryListener();

	public PageHistoryAction(IWorkbenchWindow workbenchWindow, boolean forward) {
		super("", workbenchWindow);

		ISharedImages sharedImages = getWorkbenchWindow().getWorkbench().getSharedImages();
		if (forward) {
			setText("Forward");
			setToolTipText("Forward");
			setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_FORWARD));
			setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_FORWARD_DISABLED));
			setActionDefinitionId(FORWARD);
		} else {
			setText("Back");
			setToolTipText("Back");
			setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_BACK));
			setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_BACK_DISABLED));
			setActionDefinitionId(BACK);
		}
		setEnabled(false);
		this.forward = forward;
		setMenuCreator(new MenuCreator());
	}

	@Override
	public void run() {
		if (getWorkbenchWindow() == null)
			return;

		if (activePageHistory != null) {
			if (forward)
				activePageHistory.forward();
			else
				activePageHistory.back();
		}
	}
	
	@Override
	protected void updateState() {
		IEditorPart activeEditor = getActiveEditor();
		if (activeEditor != null) {
			IEditorInput input = activeEditor.getEditorInput();
			if (input instanceof TabPartEditorInput) {
				setActivePageHistory(((TabPartEditorInput) input).getPageHistory());
				return;
			}
		}
		
		setActivePageHistory(null);
	}
	
	protected void update() {
		if (activePageHistory == null) {
			setEnabled(false);
		} else {
			setEnabled(forward ? activePageHistory.canForward() : activePageHistory.canBack());
		}
	}

	protected void setActivePageHistory(PageHistory pageHistory) {
		if (activePageHistory == pageHistory)
			return;
		if (activePageHistory != null)
			activePageHistory.removeListener(pageHistoryListener);
		activePageHistory = pageHistory;
		if (activePageHistory != null)
			activePageHistory.addListener(pageHistoryListener);
		update();
	}

	private class MenuCreator implements IMenuCreator {

		private Menu historyMenu;
		
		public Menu getMenu(Menu parent) {
			return null;
		}

		public Menu getMenu(Control parent) {
			dispose();
			historyMenu = new Menu(parent);
			IWorkbenchPage page = getActivePage();
			if (page == null)
				return historyMenu;

			// Create items
			
			PageHistoryEntry[] entries;
			if (forward)
				entries = activePageHistory.getForwardEntries(MAX_HISTORY_ENTRIES);
			else
				entries = activePageHistory.getBackEntries(MAX_HISTORY_ENTRIES);
			for (final PageHistoryEntry entry : entries) {
				MenuItem item = new MenuItem(historyMenu, SWT.NONE);
				item.setText(entry.getPageInput().getLabel());
				item.addSelectionListener(new SelectionAdapter() {

					@Override
					public void widgetSelected(SelectionEvent e) {
						activePageHistory.shiftCurrentEntry(entry);
					}
					
				});
			}
			
			return historyMenu;
		}

		public void dispose() {
			if (historyMenu != null) {
				for (int i = 0; i < historyMenu.getItemCount(); i++) {
					MenuItem menuItem = historyMenu.getItem(i);
					menuItem.setData(null);
				}
				historyMenu.dispose();
				historyMenu = null;
			}
		}

	}
	
	private class PageHistoryListener implements IPageHistoryListener {

		public void pageChanged(PageHistory history) {
			update();
		}
		
	}

}
